rm(list = ls())
setwd("~/Projects/news_tweets")
## --- Load Packages --- ##
library(rtweet)
library(dplyr)
library(ggplot2)
library(rvest)
library(tidyr)
library(wordcloud2)
library(igraph)
library(ggraph)
library(stringr)
library(tm)
library(tidytext)
library(stringi)
library(lubridate)
library(gganimate)
library(htmlwidgets)

## --- Set Stylings --- ###
knitr::opts_chunk$set(message=FALSE, warning=FALSE)

theme_set(
  theme_bw(base_size = 14) +
    theme(
      plot.title = element_text(face = "bold", size = 14, 
                                margin = margin(0, 0, 4, 0, "pt")),
      plot.subtitle = element_text(size = 12),
      plot.caption = element_text(size = 6, hjust = 0),
      axis.title = element_text(size = 10),
      panel.border = element_blank()
    )
)

## --- Global Variables --- ##
# Define Color
Mycol <- RColorBrewer::brewer.pal(8, "Dark2")

# Define http pattern
http <- paste("http.*","https.*", sep = "|")

# Define Stopwords
stopwords <- data_frame(
  word =  stopwords("german")
) %>% rbind(
  data_frame(word = c("t.co","via","mal","dass","mehr", "amp","https",
                      "beim", "ab","sollen","ganz","sagt",
                      "schon","rt","gibt", "ja", "natürlich"))
)

Deutschsprachige Tweets die den Hashtag “#GERSWE” beinhalten. Die Tweets wurden mit Hilfe des R Packetes rtweet über die REST API ausgelesen. Der gesamte Code ist hier einzusehen.

load("../../data/gerswe.Rda")
attr(rt$created_at, "tzone") <- "Europe/Berlin"

start <- as.POSIXct("2018-06-23 19:00", tz = "Europe/Berlin")
end <- start + minutes(220)

gamestart <- as.POSIXct("2018-06-23 20:00", tz = "Europe/Berlin")
gameend <- gamestart + minutes(113) 

rt_small <- rt %>% 
#  mutate(created_at = as.POSIXct(created_at + hours(2))) %>%
  filter(created_at >= start) %>%
  filter(created_at <= end) 

Zeitraum

rt_small %>%
  ts_plot("1 minute",
        color = Mycol[3]) +
  geom_vline(xintercept = gamestart, color=Mycol[1], linetype = 2) +
  geom_vline(xintercept = gameend, color=Mycol[1], linetype = 2) +
  theme(plot.title = element_text(face = "bold"),
        axis.text.x = element_blank()) +
  labs(
    x = NULL, y = NULL,
    title = "Tweets zum Spiel Deutschland - Mexiko",
    subtitle = paste("Zeitraum:",min(rt$created_at),"bis",max(rt$created_at))
  ) 

Retweets

Welche Tweets wurden am häufigsten geteilt? Die top 10 sind:

rt_small %>%
  filter(is_retweet == FALSE ) %>%
  dplyr::select(screen_name, text, retweet_count) %>%
  group_by(screen_name, text) %>%
  summarise(retweet_count = sum(retweet_count)) %>%
  arrange(desc(retweet_count)) %>%
  .[1:10,] %>%
  knitr::kable(align = "l")
screen_name text retweet_count
DFB_Team Wahnsinn in Sotschi! Wir gewinnen in Unterzahl und letzter Minute gegen Schweden.
#ZSMMN #WM2018 #GE RSWE 2-1 https://t.co/xx4G32tAut 3583
LeroySane19 Besser spät als nie 😉⚽ Glückwunsch zum Sieg Jungs, am Ende vollkommen verdient! @DFB_Team #DieMannschaft #GERSWE 1467
FCBayern 🇩🇪🇸🇪 Alter Schwede - Sieg in der Nachspielzeit!

GERSWE #DieMannschaft #WM2018 https://t.co/EH7iydh9ad 1227

RKiesewetter Schon irre, mich sprechen vor Spiel #GERSWE 2 CDU-Kollegen an, sagen offen, wenn ich weiter europafreundliche liberale Haltung wie #Merkel in Asyl-/ Migrationsfragen vertrete, würde prominenter CSUler bei der nächsten #BTW gegen mich kandidieren. Soweit lassen wir uns bringen! 1034
BVB 🇩🇪 GLÜCKWUNSCH! Last-Minute-Sieg für @woodyinho und das @DFB_Team! #Reus ebnet mit seinem Ausgleich in der 48. Minute den Weg für das deutsche Team! 🇩🇪 #GERSWE 🇸🇪 #BoRUSSIA2018 https://t.co/u6Gi9BlWCb 835
mbfussball BEST NEVER REST! Dieses Team kommt immer zurück!

@ToniKroos schießt das @DFB_Team in Führung – der Traum vom Achtelfinale lebt wieder!

GERSWE 🇩🇪🇸🇪 #BestNeverRest https://t.co/YSvol59YXi 776

ZDFsport “Fußball ist ein einfaches Spiel: 22 Männer jagen 90 Minuten einem Ball nach und am Ende gewinnen immer die Deutschen.” - Gary Lineker

GERSWE | #ZDFwm2018 https://t.co/kWt9Q3l6zp 726

anredo Wenn ich ein Wasser mit Kohlensäure bestelle aber eins ohne bekomme. #GERSWE https://t.co/e2mIwN44Ig 717
FCBayern 🇩🇪 Bärenstarke Leistung, Kapitän! ©💪 @Manuel_Neuer #GERSWE #WM2018 https://t.co/o5SM5CYWwb 676
bayer04fussball Unsere herzlichsten Glückwünsche nach Sotschi! #StärkeBayer #GERSWE 1-2 🇩🇪🇸🇪 https://t.co/BHeIFhmQgy 521

Wordcloud

rt_clean <- rt_small %>%
  # First, remove http elements manually
  mutate(stripped_text = gsub(http,"", text)) %>%
  mutate(stripped_text = gsub("gerswe","", text, ignore.case = T)) 
  
rt_tidy_words <- rt_clean %>%
  # Second, remove punctuation, convert to lowercase, add id for each tweet!
  dplyr::select(stripped_text) %>%
  unnest_tokens(word, stripped_text) %>%
  
  # Third, remove stop words from your list of words 
  anti_join(stopwords) %>%
  
  # Count Word occurences in a tweet
  count(word, sort = TRUE) 

rt_tidy_words %>%
  wordcloud2(size = 2, 
           color = "random-light", backgroundColor = "grey")

Wie sind die Wörter miteinander verlinkt?

word_network(rt_clean)

Sentiment Analyse

Lexikon Ansatz unter Verwendung des SentimentWortschatz

sent <- c(
  # positive Wörter
  readLines("../../dict/SentiWS_v1.8c_Negative.txt",
            encoding = "UTF-8"),
  # negative Wörter
  readLines("../../dict/SentiWS_v1.8c_Positive.txt",
            encoding = "UTF-8")
) %>% lapply(function(x) {
  # Extrahieren der einzelnen Spalten
  res <- strsplit(x, "\t", fixed = TRUE)[[1]]
  return(data.frame(words = res[1], value = res[2],
                    stringsAsFactors = FALSE))
}) %>%
  bind_rows %>% 
  mutate(word = gsub("\\|.*", "", words) %>% tolower,
         value = as.numeric(value)) %>%
  # manche Wörter kommen doppelt vor, hier nehmen wir den mittleren Wert
  group_by(word) %>% summarise(value = mean(value)) %>% ungroup
sentDF <- rt_clean %>%
  # Second, remove punctuation, convert to lowercase, add id for each tweet!
  unnest_tokens(word, stripped_text) %>%
  left_join(., sent, by="word") %>% 
  mutate(value = as.numeric(value)) %>% 
  #filter(!is.na(value)) %>%
  mutate(negative = ifelse(value < 0, value, NA),
         positive = ifelse(value > 0, value, NA),
         negative_d = ifelse(value < 0, 1, 0),
         positive_d = ifelse(value > 0, 1, 0)) 

Wordclouds

Positive Wörter

Negative wörter

sentDF.grouped <- sentDF %>%
  group_by(status_id) %>%
  summarise(mean_value = mean(value, na.rm = T),
            sum_value = sum(value, na.rm = T),
            positive = sum(positive, na.rm = T),
            negative = sum(negative, na.rm = T)) %>%
  left_join(., rt_small %>% dplyr::select(status_id, screen_name, text, created_at),
            by = "status_id") %>%
  filter(!is.na(mean_value))

Top 10 positive Tweets

sentDF.grouped %>%
  arrange(desc(mean_value)) %>%
  select(screen_name, text, mean_value, created_at) %>%
  .[1:10,] %>%
  htmlTable::htmlTable(align="l")
screen_name text mean_value created_at
1 Simone0171 Heute ist aber Dampf drin! Start gelungen, jetzt dran bleiben🙌🏼👏🏼👊🏼⚽️🇩🇪 #GERSWE #WorldCup18 1 2018-06-23 20:10:51
2 uelmenuelmen Die Straßen sind leergefegt. Perfekt zum drugs dealen #GERSWE 0.7299 2018-06-23 19:31:48
3 thierie01

Ich sehe #Löw hat die #Mannschaft perfekt vorbereitet. ➡️ Die Nivea-Lotion ist aufgetragen. ➡️ Die Tattoos sind geölt. ➡️ Die Haare sind perfekt gestylt.

Was soll da jetzt schon schiefgehen?

#GERSWE #FussballWM2018 #Russia2018WorldCup
0.7299 2018-06-23 19:59:57
4 enricoS74 #GerSwe perfekt!!! Es läuft!!! Auf Wiedersehen Erdogan freaks. 0.7299 2018-06-23 20:39:44
5 Telodor567 Mein Vater meinte, so wie wir spielen, das passt perfekt auf Deutschland generell heute. #GERSWE 0.7299 2018-06-23 20:53:03
6 ToniHorvatos Schweden wird gleich ultra tiefstehen. Wenn sie nur einen Flügelspieler hätten der 1v1 perfekt kann. Stattdessen ist Müller LF. #GERSWE 0.7299 2018-06-23 20:56:23
7 TitoUganj @quotenmeter DFB-Elf und ARD bilden eine homogene lahmarschige Masse. Löw mäandert unter Valium, Kimmich hat die Hosen voll, Müller verkörpert perfekt den Durchschnitt, Götze bester Deutscher und Bartels geht voll aus sich raus (“das geht so nicht”). #gerswe 0.7299 2018-06-23 21:03:35
8 MrsOrange Unser Team ist wie ein mit High Tech vollgestopftes Auto. Alles läuft perfekt und schnurrt, aber sobald irgendwo ein Kontakt wackelt, explodiert die Karre. #WM2018 #GERSWE 0.7299 2018-06-23 21:03:48
9 JonasBelling

11 Millionäre mit perfekt sitzenden Frisuren. Nur Fußball spielen können sie nicht.

GerSwe

#Sweger
0.7299 2018-06-23 21:03:59
10 _misskonfetti Die Haare liegen nicht perfekt. Das wird nix 🤦‍♀️ #GERSWE #gomez 0.7299 2018-06-23 21:04:43

Top 10 negative Tweets

sentDF.grouped %>%
  arrange(mean_value) %>%
  select(screen_name, text, mean_value, created_at) %>%
  .[1:10,] %>%
  htmlTable::htmlTable(align="l")
screen_name text mean_value created_at
1 Paeddy1994_yt Warum nennen wir #LaManschaft nicht gleich „keine Gefahr“? 🙄 #GERSWE #WM2018 -1 2018-06-23 20:08:47
2 wanderwitz Da ist die Gefahr. @Manuel_Neuer #Fußballgott! #GERSWE Aber gutes druckvolles Spiel @DFB_Team -1 2018-06-23 20:13:47
3 mainwasser Eine solch große Gefahr war Schweden für Deutschland zuletzt 1618-48. #GERSWE -1 2018-06-23 20:39:37
4 dj48jupp #GERSWE In der 40. Min schießt mal einer aus 16 m aufs Tor. Gleich Gefahr. 1/2 Minute später, versuchen sie wieder, den Ball ins Tor zu tragen. Das durch eine vielbeinige Abwehr. ???????????????? -1 2018-06-23 20:41:46
5 kfdreizehn Auf die Gefahr, das ich mich wiederhole, aber ohne defensives Mittelfeld in ein Turnier zu gehen, funktioniert äußerst selten!☝🏻 #wm2018 #GERSWE -1 2018-06-23 20:51:52
6 BastiBoers2

Mehr Gefahr? #Brandgefährlich bringen!

#GERSWE #wm2018 #Ger
-1 2018-06-23 21:13:35
7 ElCobra Auf die Gefahr hin wie ein angegammelter Altinternationaler im Doppelpass zu klingen: So viele Pseudo-Häuptlinge, kein einziger echter Anführer. #GERSWE -1 2018-06-23 21:39:23
8 Clausewutz

Die @afd wird schuld sein, wenn Schland ausscheidet

#GERSWE
-0.9686 2018-06-23 19:12:36
9 thesoftrockcafe Wenn Deutschland rausfliegt, sind definitiv nicht Özil, Draxler oder Löw schuld. Sondern die Fanta4 mit ihrem unsäglichen WM-Song! #GERSWE #wm2018 https://t.co/fvlTbORZNE -0.9686 2018-06-23 19:50:40
10 FreshFries90 Haben alle mitgesungen. Wenn es jetzt nichts wird mit dem Sieg ist die deutsche Frau schuld, die sie eingeblendet haben, die nicht mitgesungen hat #GERSWE -0.9686 2018-06-23 19:56:32

Sentiment im Zeitveraluf